﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
//using System.Transactions;


namespace DAL
{
    public partial class ExpenseLine
    {
        public static IQueryable<ExpenseLine> LoadSearchResult(Guid expenseReportId)
        {
            DataAccessDataContext db = new DataAccessDataContext();
            return from l in db.ExpenseLines
                   where l.ExpenseReportId == expenseReportId
                   select l;
        }

        public static ExpenseLine Get(Guid id)
        {
            DataAccessDataContext db = new DataAccessDataContext();
            var q = from e in db.ExpenseLines
                    where e.Id.Equals(id)
                    select e;
            int count = q.Count<ExpenseLine>();
            if (count == 1)
                return q.First<ExpenseLine>();
            else
                return null;
        }

        public void Save()
        {
            DataAccessDataContext da = new DataAccessDataContext();
            var q = from e in da.ExpenseLines
                    where e.Id.Equals(this.Id)
                    select e;
            int count = q.Count<ExpenseLine>();
            ExpenseLine el = null;
            if (count == 1)
                el = q.First<ExpenseLine>();
            if (el == null)
                da.ExpenseLines.InsertOnSubmit(this);
            else
            {
                //el = new ExpenseLine();
                el.Date = this.Date;
                el.Description = this.Description;
                el.ExpenseReportId = this.ExpenseReportId;
                el.ExpenseTypeId = this.ExpenseTypeId;
                el.Id = this.Id;
                el.Justification = this.Justification;
                el.Value = this.Value;
            }
            //da.ExpenseLines.InsertOnSubmit(this);
            da.SubmitChanges();
        }

        public static void Delete(Guid lineId)
        {
            DataAccessDataContext db = new DataAccessDataContext();
            ExpenseLine line = db.ExpenseLines.First(l => l.Id == lineId);
            if (line != null)
            {
                if (line.ExpenseLineDislocation != null)
                {
                    //db.ExpenseLineDislocations.Attach(line.ExpenseLineDislocation);
                    db.ExpenseLineDislocations.DeleteOnSubmit(line.ExpenseLineDislocation);
                }
                if (line.ExpenseLineSimple != null)
                {
                    //db.ExpenseLineSimples.Attach(line.ExpenseLineSimple);
                    db.ExpenseLineSimples.DeleteOnSubmit(line.ExpenseLineSimple);
                }
                //db.ExpenseLines.Attach(line);
                db.ExpenseLines.DeleteOnSubmit(line);
                db.SubmitChanges();
            }
        }

        //public void Delete()
        //{
        //    DataAccessDataContext db = new DataAccessDataContext();
        //    if (this.ExpenseLineDislocation != null)
        //    {
        //        db.ExpenseLineDislocations.Attach(this.ExpenseLineDislocation);
        //        db.ExpenseLineDislocations.DeleteOnSubmit(this.ExpenseLineDislocation);
        //    }
        //    if (this.ExpenseLineSimple != null)
        //    {
        //        db.ExpenseLineSimples.Attach(this.ExpenseLineSimple);
        //        db.ExpenseLineSimples.DeleteOnSubmit(this.ExpenseLineSimple);
        //    }
        //    db.ExpenseLines.Attach(this);
        //    db.ExpenseLines.DeleteOnSubmit(this);
        //    db.SubmitChanges();

        //}

        /**
         * Este método vai ler o template da cadeia e
         * iniciar uma nova instância deste! Deve ser apenas
         * chamado uma vez! Caso isso ocorra, vai fazer
         * reset à chain!
         * 
         */
        //public static bool StartNewChain(Guid expenseid)
        //{
        //    using (TransactionScope tc = new TransactionScope())
        //    {
        //        using (DataAccessDataContext dc = new DataAccessDataContext())
        //        {
        //            XElement doc;

        //            var query = from el in dc.ExpenseLines
        //                        where el.Id.Equals(expenseid)
        //                        select el;

        //            ExpenseLine e = query.Single<ExpenseLine>();

        //            var query2 = from el2 in dc.ExpenseTypes
        //                         where el2.Id.Equals(e.ExpenseTypeId)
        //                         select el2;

        //            ExpenseType t = query2.Single<ExpenseType>();

        //            var query3 = from chain in dc.Chains
        //                         where chain.id.Equals(t.Chain)
        //                         select chain;

        //            Chain c = query3.Single<Chain>();

        //            doc = c.xml;
        //            doc.SetAttributeValue("id", e.Id);
        //            doc.SetAttributeValue("level", 1);
        //            doc.SetAttributeValue("rejected", false);

        //            foreach (XElement xe in doc.Elements())
        //            {
        //                xe.SetAttributeValue("notified", false);
        //                xe.SetAttributeValue("authorized", false);
        //            }

        //            e.ChainState.RemoveAll();
        //            dc.SubmitChanges();

        //            e.ChainState = new XElement(doc);
        //            dc.SubmitChanges();
        //            tc.Complete();
        //            return true;
        //        }
        //    }

        //}


        ///**
        // * Este método vai ler a cadeia e devolver
        // * os autorizadores do nível currente de
        // * aprovação
        // * 
        // */
        //public static Guid[] RetrieveNextLevelOfAuthorizers(Guid expenseid)
        //{
        //    using (TransactionScope tc = new TransactionScope())
        //    {
        //        using (DataAccessDataContext dc = new DataAccessDataContext())
        //        {
        //            XElement doc = RetriveChainState(expenseid, dc);

        //            if (doc == null)
        //                throw new Exception("Chain state is empty! Please call StartNewChain method!");

        //            List<Guid> aut = new List<Guid>();

        //            //Nivel currente
        //            String lvl = doc.Attribute("level").Value;
        //            String current_level;

        //            foreach (XElement x in doc.Elements())
        //            {
        //                current_level = x.Attribute("level").Value;
        //                if (current_level.Equals(lvl))
        //                    aut.Add(new Guid(x.Attribute("id").Value));
        //            }
        //            return aut.ToArray();
        //        }
        //    }
        //}


        ///**
        // * Utilizar este método para rejeitar uma despesa
        // * 
        // */
        //public static bool RejectExpense(Guid expenseid, String userid, String justification)
        //{
        //    using (TransactionScope tc = new TransactionScope())
        //    {
        //        using (DataAccessDataContext dc = new DataAccessDataContext())
        //        {
        //            LinkedList<Guid> deplevels = RetrieveAllDepartmentsAssociatedWithUser(userid, dc);

        //            var query = from el in dc.ExpenseLines
        //                        where el.Id.Equals(expenseid)
        //                        select el;

        //            ExpenseLine e = query.Single<ExpenseLine>();

        //            XElement chain = e.ChainState;

        //            if (chain.Attribute("rejected").Value.Equals("True") || chain.Attribute("level").Value.Equals("-1"))
        //                return false;

        //            //Isto vai fazer lock à cadeia e não vai ser possível mais updates
        //            chain.Attribute("rejected").Value = true.ToString();


        //            foreach (Guid deplvl in deplevels)
        //            {
        //                XAttribute attr;
        //                foreach (XElement x in chain.Elements())
        //                {
        //                    attr = x.Attribute("id");
        //                    if (attr.Value.Equals(deplvl.ToString()))
        //                        x.SetAttributeValue("authorized", false);
        //                }
        //            }

        //            e.ChainState = new XElement(chain);

        //            CheckAndUpdateLevel(e);

        //            dc.SubmitChanges();
        //            tc.Complete();                    
        //        }               

        //        return true;

        //    }
        //}

        ///**
        // * Utilizar este método para autorizar uma despesa
        // * 
        // */
        //public static bool AcceptExpense(Guid expenseid, String userid)
        //{
        //    using (TransactionScope tc = new TransactionScope())
        //    {
        //        using (DataAccessDataContext dc = new DataAccessDataContext())
        //        {
        //            LinkedList<Guid> deplevels = RetrieveAllDepartmentsAssociatedWithUser(userid, dc);

        //            var query = from el in dc.ExpenseLines
        //                        where el.Id.Equals(expenseid)
        //                        select el;

        //            ExpenseLine e = query.Single<ExpenseLine>();

        //            XElement chain = e.ChainState;

        //            if (chain.Attribute("rejected").Value.Equals("True") || chain.Attribute("level").Value.Equals("-1"))
        //                return false;


        //            foreach (Guid deplvl in deplevels)
        //            {
        //                XAttribute attr;
        //                foreach (XElement x in chain.Elements())
        //                {
        //                    attr = x.Attribute("id");
        //                    if (attr.Value.Equals(deplvl.ToString()))
        //                        x.SetAttributeValue("authorized", true);
        //                }
        //            }

        //            e.ChainState = new XElement(chain);
        //            CheckAndUpdateLevel(e);
        //            dc.SubmitChanges();
        //            tc.Complete();
        //        }

        //        return true;

        //    }
        //}


        ///**
        // * Utilizar para verificar se cadeia está completa
        // * 
        // * */
        //public static bool ApprovalComplete(Guid expenseid)
        //{
        //    using (TransactionScope tc = new TransactionScope())
        //    {
        //        using (DataAccessDataContext dc = new DataAccessDataContext())
        //        {
        //            var query = from el in dc.ExpenseLines
        //                        where el.Id.Equals(expenseid)
        //                        select el;

        //            ExpenseLine e = query.Single<ExpenseLine>();

        //            if (e.ChainState.Attribute("rejected").Value.Equals("False"))
        //                return false;
        //            else if (e.ChainState.Attribute("level").Value.Equals("-1"))
        //                return true;
        //            else return false;
        //        }
        //    }
        //}

        ////HELPER METHODS
        //private static XElement RetriveChainState(Guid expenseid, DataAccessDataContext dc)
        //{
        //    var query = from el in dc.ExpenseLines
        //                where el.Id.Equals(expenseid)
        //                select el;

        //    ExpenseLine e = query.Single<ExpenseLine>();
        //    return e.ChainState;
        //}

        //private static void CheckAndUpdateLevel(ExpenseLine el)
        //{
        //    String lvl = el.ChainState.Attribute("level").Value;
        //    XAttribute attr;
        //    bool allAproved = true;
        //    XElement doc = el.ChainState;

        //    //Verificar para o nivel currente se todos estão autorizados
        //    foreach (XElement x in doc.Elements())
        //    {
        //        attr = x.Attribute("level");
        //        if (attr.Value.Equals(lvl))
        //        {
        //            attr = x.Attribute("authorized");
        //            if (attr.Value.Equals("false"))
        //            {
        //                allAproved = false;
        //            }
        //        }
        //    }

        //    //Por level a -1 caso os niveis estejam todos aprovados
        //    if (allAproved)
        //    {
        //        if (doc.Attribute("level").Value.Equals(el.ChainState.Attribute("maxLevel").Value))
        //        {
        //            doc.Attribute("level").Value = "-1";
        //            el.ChainState = new XElement(doc);
        //        }

        //        else
        //        {
        //            doc.Attribute("level").Value = "" + (int.Parse(lvl) + 1);
        //            el.ChainState = new XElement(doc);
        //            CheckAndUpdateLevel(el);
        //        }
        //    }


        //}

        //private static LinkedList<Guid> RetrieveAllDepartmentsAssociatedWithUser(string userid, DataAccessDataContext dc)
        //{
        //    LinkedList<Guid> deps = new LinkedList<Guid>();
        //    var query = from deplevel in dc.UserDepartments
        //                where deplevel.iduser.Equals(userid)
        //                select deplevel;

        //    foreach (UserDepartment ud in query)
        //        deps.AddFirst(ud.iddeplevel);

        //    return deps;                       
        //}
    }
}
